package com.specialized.coupon.service.impl;

import java.math.BigDecimal;
import java.time.LocalTime;
import java.time.temporal.TemporalAccessor;
import java.util.*;

import cn.hutool.core.date.DateTime;
import com.specialized.common.core.domain.Result;
import com.specialized.common.core.exception.ServiceException;
import com.specialized.common.core.utils.DateUtils;
import com.specialized.common.core.utils.DesUtils;
import com.specialized.common.redis.service.RedisService;
import com.specialized.common.security.utils.SecurityUtils;
import com.specialized.coupon.config.CouponEnum;
import com.specialized.coupon.domain.*;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import com.specialized.coupon.mapper.CouponMapper;
import com.specialized.coupon.service.ICouponService;

/**
 * 优惠卷用户关系Service业务层处理
 *
 * @author djh
 * @date 2024-07-19
 */
@Service
public class CouponServiceImpl implements ICouponService {
    @Autowired
    private CouponMapper couponMapper;
    @Autowired
    private RedisService redisService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private InviteServiceImpl service;
    @Autowired
    private RedissonClient client;
    private static final String KEY = "~@#$y1a2n.&@+n@$%*(1)";

    /**
     * 查询优惠卷用户关系
     *
     * @param userCouponId 优惠卷用户关系主键
     * @return 优惠卷用户关系
     */
    @Override
    public Coupon selectCouponByUserCouponId(Long userCouponId) {
        return couponMapper.selectCouponByUserCouponId(userCouponId);
    }

    /**
     * 查询优惠卷用户关系列表
     *
     * @param coupon 优惠卷用户关系
     * @return 优惠卷用户关系
     */
    @Trace
    @Tag(key = "selectCouponList",value = "returnedObj")
    @Override
    public List<Coupon> selectCouponList(Coupon coupon) {
        Long userId = SecurityUtils.getUserId();
        coupon.setUserId(userId);
        return couponMapper.selectCouponList(coupon);
    }

    /**
     * 新增优惠卷用户关系
     *
     * @param coupon 优惠卷用户关系
     * @return 结果
     */
    @Override
    public int insertCoupon(Coupon coupon) {
        coupon.setCreateTime(DateUtils.getNowDate());
        return couponMapper.insertCoupon(coupon);
    }

    /**
     * 修改优惠卷用户关系
     *
     * @param coupon 优惠卷用户关系
     * @return 结果
     */
    @Override
    public int updateCoupon(Coupon coupon) {
                coupon.setUpdateTime(DateUtils.getNowDate());
        return couponMapper.updateCoupon(coupon);
    }

    /**
     * 批量删除优惠卷用户关系
     *
     * @param userCouponIds 需要删除的优惠卷用户关系主键
     * @return 结果
     */
    @Override
    public int deleteCouponByUserCouponIds(Long[] userCouponIds) {
        return couponMapper.deleteCouponByUserCouponIds(userCouponIds);
    }

    /**
     * 删除优惠卷用户关系信息
     *
     * @param userCouponId 优惠卷用户关系主键
     * @return 结果
     */
    @Override
    public int deleteCouponByUserCouponId(Long userCouponId) {
        return couponMapper.deleteCouponByUserCouponId(userCouponId);
    }

    @Override
    public Result getUrl() {
        Long userId = SecurityUtils.getUserId();
        String url="";
        String encodeDES="";
        try {

            encodeDES = DesUtils.encodeDES(KEY, userId.toString());
            url = "http://127.0.0.1/register?userId="+encodeDES;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(url);
    }

    @Override
    public Result invite(InviteDto dto) {
        try {
            Long userId = SecurityUtils.getUserId();
            String url = dto.getUrl();
            String[] split = url.split("=");
            String s = DesUtils.decodeDES(KEY, split[1]);
            System.out.println(s);
            if(s.equals(userId.toString())){
                Invite invite = new Invite();
                invite.setUserId(Long.valueOf(s));
                invite.setCode(dto.getUrl());
                invite.setCreateTime(new Date());
                service.insertInvite(invite);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(200,"邀请成功");
    }

    @Override
    public Result couponSnatching(Long sessionId) {
        Map<String, Object> cacheMap = redisService.getCacheMap("COUPON");
        List<CouponSession> list1 = new ArrayList<>();
        for (Map.Entry<String, Object> entry : cacheMap.entrySet()) {
            String purchaseSessionsId = entry.getKey();
            String[] split = purchaseSessionsId.split(",");
            CouponSession value = (CouponSession) entry.getValue();
            if(split[0].equals(sessionId.toString())){
                list1.add(value);
            }
        }
        return Result.success(list1);
    }

    @Override
    public Result findSession() {
        List<Session> session = couponMapper.findSession();
        return Result.success(session);
    }

    @Override
    public Result getRandom() {
        UUID uuid = UUID.randomUUID();
        redisService.setCacheObject(uuid.toString(),uuid.toString());
        return Result.success(uuid);
    }

    @Override
    public Result snatching(Long sessionId,Long couponId) {

//        Boolean b = redisService.hasKey(session.getUuid());
        CouponSession cacheMapValue = redisService.getCacheMapValue("COUPON",sessionId.toString()+","+couponId.toString());
        Long userId = SecurityUtils.getUserId();
        if(cacheMapValue==null){
            throw new ServiceException("该优惠卷不存在");
        }
        DateTime dateTime = new DateTime();
        LocalTime now = LocalTime.now();
        if(cacheMapValue.getStartTime().getDate()>dateTime.getDate()||cacheMapValue.getEndTime().getDate()<dateTime.getDate()){
            throw new ServiceException("不在活动时间内",505);
        }
        if((cacheMapValue.getStartDateTime().getHours()>now.getHour())||(cacheMapValue.getEndDateTime().getHours()<now.getHour())){
            throw new ServiceException("当前场次未开启",505);
        }

        ArrayList<String> keys = new ArrayList<>();
        //扣减库存
        keys.add(CouponEnum.KEY_PREFIX.getDescription()+cacheMapValue.getSessionId().toString()+","+cacheMapValue.getCouponId().toString());
        //防止重复操作
        keys.add(CouponEnum.KEY_PREFIX.getDescription()+cacheMapValue.getSessionId().toString()+cacheMapValue.getCouponId().toString()+userId);
        Long execute = redisTemplate.execute(
                LOCK_SCRIPT,
                keys,
                cacheMapValue.getNum().toString()
        );
        if(execute.equals(2L)){
            throw  new ServiceException("不可重复秒杀",505);
        }
        if(execute.equals(0L)){
            throw new ServiceException("优惠卷数量不足",505);
        }
        Coupon coupon = new Coupon();
        coupon.setCouponId(cacheMapValue.getCouponId());
        coupon.setUserId(userId);
        coupon.setCouponTitle(cacheMapValue.getCouponDescription());
        coupon.setCouponAmount(cacheMapValue.getCouponAmount());
        coupon.setCouponStatus(0L);
        coupon.setStartTime(cacheMapValue.getStartTime());
        coupon.setEndTime(cacheMapValue.getEndTime());
        couponMapper.insertCoupon(coupon);
        return Result.success("抢券成功");
    }

    @Override
    public Result getCoupon() {
        List<CouponSession> couponSession = couponMapper.findCouponSession();
        System.out.println(couponSession);
        return Result.success(couponSession);
    }

    /**
     * 初始化lua脚本
     */
    private static final DefaultRedisScript<Long> LOCK_SCRIPT;
    static {
        LOCK_SCRIPT = new DefaultRedisScript<>();
        LOCK_SCRIPT.setLocation(new ClassPathResource("lock.lua"));
        LOCK_SCRIPT.setResultType(Long.class);
    }

    @XxlJob("synchronization")
    public void synchronization(){
        List<CouponSession> couponSession = couponMapper.findCouponSession();
        couponSession.forEach(session ->
                redisService.setCacheMapValue("COUPON", session.getSessionId()+","+session.getCouponId().toString(), session)
        );
    }
    @XxlJob("synchronousRedisCouponNum")
    public void synchronousRedisCouponNum(){
        //将redis的数量
        Map<String, Object> cacheMap = redisService.getCacheMap("COUPON");
        for (Map.Entry<String, Object> entry : cacheMap.entrySet()) {
            String purchaseSessionsId = entry.getKey();
            CouponSession couponSession = new CouponSession();
            String s1 = redisTemplate.opsForValue().get("redissonLock_" + purchaseSessionsId);
            couponSession.setNum(Integer.valueOf(s1));
            String[] split = purchaseSessionsId.split(",");
            couponSession.setCouponId(Long.valueOf(split[0]));
            couponSession.setSessionId(Long.valueOf(split[1]));
            couponMapper.updateCouponSession(couponSession);
        }
    }
}
